BigDbServer.php

<?php

namespace Tlf\BigDb\Test;

class BigDbServer extends \Tlf\Tester {

    public function prepare(){
        require_once($this->file('test/input/BigDbApp/ArticleDb.php'));
        require_once($this->file('test/input/BigDbApp/orm/Article.php'));
        require_once($this->file('test/input/BigDbApp/orm/Author.php'));
        require_once($this->file('test/input/BigDbApp/orm/Tag.php'));


        require_once($this->file('test/input/BigDbTasks/TasksDb.php'));
        require_once($this->file('test/input/BigDbTasks/orm/Task.php'));
        // require_once($this->file('test/input/BigDbApp/orm/Author.php'));
        // require_once($this->file('test/input/BigDbApp/orm/Tag.php'));
    }

    public function testAccess(){
        // I decided to disable this test, because I can't figure out how to integrate access into this system.
        // I WANT it, but upon further thought (see my commented notes below), I don't think access really belongs within the db layer.
        // The DB should not know or care about users & access. That's the application's job, typically during route resolution AFTER loading items from the database.
        // The PROBLEM with this is ... I KNOW access is an important part of any public-facing system, and I want to provide a solution for this.
        // I just don't know how to do it in a reasonable way.
        // So, I'm going to call it, start using it, and probably come back to this access question later.
        $this->disable();

        return;
        $pdo = $this->getPdo();

        $art = new \Tlf\BigDb\Test\ArticlesDb($pdo);

        $server = new \Tlf\BigDbServer();
        // $server->addDatabase(Tlf\BigDb\Test\ArticlesDb::class);
        $server->addDatabase(new \Tlf\BigDb\Test\ArticlesDb($pdo));
        $server->addDatabase(new \Tlf\BigDb\Test\TasksDb($pdo));
        $server->tasks->addSqlDir($this->file('test/input/BigDbServer/TaskSql'), true);

        $server->tasks->recompile_sql();
        $server->tasks->migrate(0,1);

        // example situation:
        // A user tries to view an article that is private
        // access is denied because the user is not the author or an admin
        //
        // Access Layers:
        // On the orm: If active user is the author, access is granted.
            // authorship is specific to articles 
        // On the database layer: If article is public, access is granted.
            // public/private is used across all (or most) tables in this db library
        // On the bigdb server layer: Access is granted if user is an admin, regardless of lower-level checks
            // 

        // so,
        // the point of an access layer is to control which USERs have access to data. This is not inherint to a db structure
        // but rather is about the needs & desires of the website.
        // The ORM should not be deciding who has access to it, because the orm should typically have no concept of users 
        // An article knows about authors, but should not know about the abstract concept of a user. 
        // The webserver needs to understand the relationship beetween an author and a user, because the webserver integrates the two.
        //
        // So what role can the BigDb layer play? What awareness should a database layer have? It should know about its own ORMs, queries, migrations. It should not know about the broader system, and it should know nothing of usership.
        //
        // BigDb is responsible for loading data from the database. It, I think, should allow some kind of extensibility/integration for access controls.
        // So, it should essentially ask the system (which it's not informed about) if THIS ROW can be returned, or INSERTED, or whatever.
        //
        //

        // This is all too abstract. I need a more concrete example.
        // /article/{slug}/ is requested.
        // a Private Article is loaded from database.
        // The user is NOT an admin, NOR the author
        // Access is denied <-- Q1: Where does THIS happen
        // An error page is displayed.
        //
        // Q1: within the route-code. 
        // The route will check 
            // if author == cur_user
            // OR if cur_user == admin
            // OR if article.status == public

    }

    public function testBigDbServer(){

        
        $pdo = $this->getPdo();

        $art = new \Tlf\BigDb\Test\ArticlesDb($pdo);

        $server = new \Tlf\BigDbServer();
        // $server->addDatabase(Tlf\BigDb\Test\ArticlesDb::class);
        $server->addDatabase(new \Tlf\BigDb\Test\ArticlesDb($pdo));
        $server->addDatabase(new \Tlf\BigDb\Test\TasksDb($pdo));
        $server->tasks->addSqlDir($this->file('test/input/BigDbServer/TaskSql'), true);

        $server->tasks->recompile_sql();
        $server->tasks->migrate(0,1);

        $this->test("Migrate, sql, and query_rows work for TasksDb added to BigDbServer");
        $tasks = $server->tasks->query_rows('task.get_overdue');
        $task_titles = array_map(function($row){return $row['title'];}, $tasks);
        $this->compare_arrays(
            ['Jog', 'Walk', 'Read'],
            $task_titles
        );


        $this->test("SQL Query for incomplete future tasks.");
        $tasks = $server->tasks->sql_query('SELECT `title` FROM `task` WHERE `due_date` > CURRENT_TIMESTAMP AND `date_completed` IS NOT NULL');
        $this->compare_arrays(
            [0=>['title'=>'Get Cleaning Supplies'],
             1=>['title'=>'Buy Shoes']
            ],
            $tasks
        );

        $this->test("User supplied stored sql works");
        $stored_tasks = $server->tasks->query_rows('task.get_incomplete_future_tasks');
        $this->compare_arrays(
            $tasks,
            $stored_tasks
        );

        ###
        
        // Add user-defined access settings
        // then test both allowing & denying access to some rows.
    }
}